/**
 * 
 */
package jnzb.binding;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import jnzb.nzb.File;
import jnzb.nzb.NZB;
import jnzb.nzb.Segment;
import nanoxml.XMLElement;
import nanoxml.XMLParseException;

/**
 * Rather than using an XML-Java binding utility, which would be easy, but way
 * over the top and have massive overheads, I'll manually do the binding using
 * the NanoXML-Lite XML parser.
 * 
 * This is a factory to get an NZB object from an NZB file
 * 
 * @author Rid
 * 
 */
public class NZBBinder {

	private static final NZBBinder INSTANCE = new NZBBinder();

	private NZBBinder() {

	}

	public static NZB loadFromFile(String filename) throws XMLParseException,
			IOException {

		// Constructor should call this!
		NZB nzb = new NZB();

		XMLElement nzbFile = new XMLElement();
		Reader r = new FileReader(filename);
		nzbFile.parseFromReader(r);

		// Enumerate over all file elements
		Enumeration<XMLElement> fileElements = nzbFile.enumerateChildren();
		List<File> files = new ArrayList<File>();

		while (fileElements.hasMoreElements()) {
			XMLElement fileElement = fileElements.nextElement();
			if (fileElement.getName().equalsIgnoreCase("file")) {
				if (fileElement.countChildren() == 2) {
					File file = new File();
					file.setPoster(fileElement.getStringAttribute("poster"));
					file.setDate(fileElement.getIntAttribute("date"));
					file.setSubject(fileElement.getStringAttribute("subject"));

					// Get groups
					file.setGroups(processGroups(getChild(fileElement,
									"groups")));
					// Get segments
					file.setSegments(processSegments(getChild(fileElement,
							"segments")));

					files.add(file);
				} else {
					throw new XMLParseException(
							"Expected 2 elements per file element", null);
				}
			} else {
				throw new XMLParseException("Expected file element", null);
			}
		}
		nzb.setFiles(files);
		r.close();
		return nzb;
	}

	private static List<String> processGroups(XMLElement groups) {
		List<String> allGroups = new ArrayList<String>();

		Enumeration<XMLElement> groupList = groups.enumerateChildren();
		while (groupList.hasMoreElements()) {
			XMLElement group = groupList.nextElement();
			allGroups.add(group.getContent());
		}
		return allGroups;
	}

	private static List<Segment> processSegments(XMLElement segments) {
		List<Segment> allSegments = new ArrayList<Segment>();
		
		// Enumerate over all segment elements
		Enumeration<XMLElement> allSegment = segments.enumerateChildren();
		while (allSegment.hasMoreElements()){
			XMLElement segmentElement = allSegment.nextElement();
			Segment segment = new Segment();
			
			segment.setBytes(segmentElement.getIntAttribute("bytes"));
			segment.setNumber(segmentElement.getIntAttribute("number"));
			segment.setMessageID(segmentElement.getContent());
			
			allSegments.add(segment);
		}
		return allSegments;
	}

	private static XMLElement getChild(XMLElement element, String child) {
		Enumeration<XMLElement> children = element.enumerateChildren();
		while (children.hasMoreElements()) {
			XMLElement kid = children.nextElement();
			if (kid.getName().equals(child)) {
				return kid;
			}
		}
		return null;
	}
}
